home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PC_LIBS / C045.ZIP / CPR.ARC / CPR.C next >
Text File  |  1988-05-30  |  47KB  |  1,315 lines

  1. /*
  2.     CPR.C            " Prints 'C' Files with Table of Contents "
  3.                      "             AND LOTS MORE               "
  4.  
  5.     Turbo C Version 1.0 or 1.5
  6.  
  7. Originally Written by :
  8.         Paul Breslin
  9.         Human Computing Resources Corp.
  10.         10 South Mary Street
  11.         Toronto, Ontario
  12.         Canada, M4Y 1P9
  13.  
  14. Modified by :
  15.         Lance E. Shepard        Rick Wise                Blake McBride
  16.         CCI & RIT                CALCULON Corp.            3900 SW 52nd Ave. #803
  17.         Rochester, NY            Rockville, MD 20850        Pembroke Park, FL 33023
  18.  
  19.         John Stidd                Dale Loftis
  20.         1570 Neston Way            3020 Yorba Linda #F-16
  21.         Los Altos, CA 94022        Fullerton, CA 92631
  22.  
  23. Special Notes:
  24.     A.)  Table of Contents is held in Local Data Segment
  25.            So Compile This Program as SMALL (at Minimum).
  26. */
  27. /* *************************************************************************
  28. **                        Program Revision History
  29. **
  30. **  By Dale Loftis
  31. **  10-3-87   Changed WIDTH to 132, Tabs are now every 4, modified so
  32. **             that temporary file is deleted if control - break is hit,
  33. **             Improved the clarity of the instructions if no parmeters
  34. **              are given.
  35. **
  36. **  10-17-87  Changed so that no blank lines are printed in between structures.
  37. **
  38. **  11-06-87  Added -@ RESPONSE FILE feature since you couldn't fit all the
  39. **             filenames onto the command line, upto 400 files can be printed.
  40. **
  41. **            Also adding the "Reading file # x of y" string and made program
  42. **             check the amount of free disk space before writing the files
  43. **             as the program would write the output file and run out of disk
  44. **             space and just put alot of junk on the disk.
  45. **
  46. **  11-08-87  Ver 1.0    Added -h HEADER FILE, -* "Print All 'C' Files,
  47. **                             -x Extra Lines and Program Version Number
  48. **
  49. **  01-10-88  Ver 1.1    Added call to setvbuf() to speed up file access.
  50. **
  51. **  01-25-88  Ver 1.2    Added -t  for option of just table of contents list
  52. **
  53. **  01-29-88  Ver 1.3    Fixed Bug.  funcname () would not be put in Table of
  54. **                         Contents because of space between funcname and ().
  55. **
  56. **  04-26-88  Ver 1.4    Added -p* option for starting page number and changed
  57. **                       Table of Contents so File Date and Time Shown.
  58. **
  59. **  05-12-88  Ver 1.5    Added -q* option to print files by section number
  60. **                       rather than by page number.
  61. **                       Added -t- option to suppress the Table of Contents
  62. */
  63. /* --------------------------------------------------------------------- */
  64. /*
  65.        Include Files for Library Function Prototypes
  66. */
  67. #include    <stdio.h>
  68. #include    <fcntl.h>
  69. #include    <alloc.h>
  70. #include    <dos.h>
  71. #include    <dir.h>
  72. #include    <conio.h>
  73. #include    <ctype.h>
  74. #include    <time.h>
  75. #include    <string.h>
  76. /* --------------------------------------------------------------------- */
  77. /*
  78.        Some Valuable Definitions
  79. */
  80. #define        O_RAW  O_BINARY                /* Handle File as Binary       */
  81.  
  82. #define        TEMPORARY_FILENAME    "CPR$.TMP"    /* temporary file name (always)*/
  83.  
  84. #define        MAJOR_VERSION    3            /* Current Software Version #   */
  85. #define        MINOR_VERSION    0
  86.  
  87. #define        BP                0x0C        /* Form feed                    */
  88. #define        COMPRESSED        0x0F        /* Compressed Print             */
  89. #define        MAX_S            256            /* Maximum string length        */
  90. #define        LENGTH            66            /* Default Page Length          */
  91. #define        WIDTH            132            /* Default page width           */
  92. #define        N_FILES            400            /* Maximum number of files      */
  93. #define        TOC_LEN            1024        /* Max Table of Contents entries*/
  94. #define        MAX_FNAME_SIZE    25            /* Max filename length in response file */
  95. #define        MAX_HDR_BYTES    500            /* Max bytes in header file     */
  96. #define        HEADER_SIZE        3            /* Header is 3 lines big        */
  97. /* -------------------------------------------------------------------------
  98. /* These Macros are used to determine valid characters for Table of Contents
  99. */
  100.  
  101. /* returns true if letter, digit, '_' or ' '*/
  102.  
  103. #define isidchr(c)      (isalnum(c) || (c == '_') || (c == ' '))
  104.  
  105. /* returns true if letter, digit, '_', '*', '\t' or '\n' */
  106.  
  107. #define isiechr(c)      (isidchr(c) || c=='*' || c=='\t' || c=='\n')
  108. /* --------------------------------------------------------------------- */
  109. /*
  110.        Internal Program Function Prototypes
  111. */
  112. int        c_break(void);        /* Called when BREAK is hit                  */
  113. int        file_stats(char *);    /* File Statistics function                  */
  114. char    *Rs();                /* Strips trailing blanks from string        */
  115. char    *EndComment();        /* Process string until end of comment       */
  116. char    *EndString();        /* Process string until end of quoted string */
  117. char    *expand();            /* Process string expanding TABS to Spaces   */
  118. char    *substr1();
  119. /* -------------------------------------------------------------------- */
  120. /*
  121.        Global Variables
  122. */
  123. FILE    *TempFile;                        /* Program Temporary File       */
  124. FILE    *File;                            /* Current File being worked on */
  125. FILE    *Rfile;                            /* Response File handle         */
  126. FILE    *Hfile;                            /* Header   File handle         */
  127.  
  128. struct ffblk fblock;            /* struct used for calculating file size */
  129. struct dfree disk_space;        /* struct used for finding free disk space */
  130.  
  131. char  file_time_buff[20];        /* file time is placed here      */
  132. char  file_date_buff[20];        /* file date is placed here      */
  133.  
  134. int        Braces;                    /* Keeps track of brace depth    */
  135. int        LineNumber;                /* Count output lines             */
  136. int        PageNumber = 1;            /* You figure this one out       */
  137. int        SectionNumber = 1;        /* and this one to               */
  138. int        PageLength = LENGTH;    /* Normal paper length           */
  139. int        PageWidth  = WIDTH;        /* normal page width             */
  140. int        OnePerPage = 0;            /* non-zero puts 1 function/page */
  141. int        NumLines   = 0;            /* non-zero puts line # in file  */
  142. int        Number     = 1;
  143. int        WantSorted = 1;            /* Sort the table of contents   */
  144. int        PageEnd;                /* Accounts for space at bottom */
  145. int        InComment;                /* Indicates if inside Comment  */
  146. int        InString;                /* Indicates if inside String   */
  147. int        double_strike;            /* # of times + 1 to write filename             */
  148. int        header_flag;            /* non-zero enables print codes/Dates/Page #'s  */
  149. int        header_lines;            /* number of extra lines from header file       */
  150. int        extra_lines;            /* non-zero enables extra lines after functions */
  151. int        table_contents;            /* non-zero indicates Table of Contents Only */
  152. int        sectionflg;                /* non-zero indicates print by section */
  153.  
  154. unsigned long    memfree;        /* amount of local memory left for file buffer  */
  155.  
  156. char    *TempName;                /* pointer to temporary filename   */
  157. char    *fname[N_FILES];        /* file names to be worked on      */
  158. char    *STDIN = "\n";          /* special string pointer value to */
  159.                                 /* flag a file as being stdin      */
  160. char    *Name;                    /* Current file name               */
  161. char    *ProgName;                /* This programs Path and Name     */
  162.  
  163. char    *Toc[TOC_LEN];            /* pointers to files in TOC        */
  164. int     TocPages[TOC_LEN];        /* page numbers                    */
  165. int     TocCount;                /* index into TOC arrays           */
  166.  
  167. char    header_buffer[MAX_HDR_BYTES];/* 500 byte buffer for user defined Page Headers */
  168. char    FunctionName[100];                /* Work area for parsing Func names */
  169. char    Todayv[45];                        /* Today's Time and Date         */
  170.  
  171. /* --------------------------------------------------------------------- */
  172. /*
  173.      The filenames[N_FILES][25] array allocates an array capable of holding
  174.     N_FILES filenames that are up to 25 characters long.
  175.  
  176.      Each filename in DOS can be 12 characters long and the response file
  177.     has a CRLF with each line and we also need a terminating zero byte
  178.     bringing the count up to 15. MAX_FNAME_SIZE bytes are provided for a
  179.     possible path
  180. */
  181. /* --------------------------------------------------------------------- */
  182. char filenames[N_FILES][MAX_FNAME_SIZE];    /* files read from response file */
  183.  
  184. /* --------------------------------------------------------------------- */
  185. /*
  186. **  The following string is the definition of tab stops.  Every 'T' is a
  187. **  tab, any other character is not.  It is currently defined as a tab
  188. **  every 4 spaces.  The comment below helps if you want to modify this,
  189. **  each row being 0+n, 50+n, 100+n, and 150+n, where n is the number
  190. **  above the declaration.  Don't try to number each row with a comment,
  191. **  because you'll notice that the '\'s make it one big string.
  192. */
  193. char   *TabDef = "\
  194. ---T---T---T---T---T---T---T---T---T---T---T---T--\
  195. -T---T---T---T---T---T---T---T---T---T---T---T--T-\
  196. ---T---T---T---T---T---T---T---T---T---T---T---T--\
  197. -T---T---T---T---T---T---T---T---T---T---T---T---T";
  198. /* ------------------------------------------------------------------------ */
  199. /*
  200. /*    Program Instructions (Note the %??? arguments)
  201. /*
  202. */
  203. char option_list[] = "\n\
  204. ----------------------------- VERSION %d.%d SWITCHES ------------------------\n\
  205.            -@*    Replace * with Response Filename (1 filename per line    )\n\
  206.            -a*    Replace * with Drive Wildcard\n\
  207.            -c     Printer Codes/Dates/Page #'s off (default is Enabled     )\n\
  208.            -d     Double Strike Printing Enabled   (default is Disabled    )\n\
  209.            -h*    Replace * with Header Filename\n\
  210.            -l##   Replace ## with PageLength       (default = %3d          )\n\
  211.            -n     Numbers Source Lines             (Resets to 1 w/each file)\n\
  212.            -o     Places 1 function on a Page      (default is multiple    )\n\
  213.            -p*    Replace * with starting Page Number\n\
  214.            -q*    Replace * with starting Section Number\n\
  215.            -s     Sort Table of Contents by Page # (default is Func. Name  )\n\
  216.            -t     Print Table of Contents Only     (-t- suppress's Table   )\n\
  217.            -w##   Replace ## with Width            (default = %3d          )\n\
  218.            -x     Enables Extra Lines after Functions (default is Disabled )\n\
  219.           [...]   Means multiple filenames may be listed\n\n\
  220.                Response Files should have 1 filename per line up to %d      \n\
  221.          characters followed by 1 CRLF and may contain up to %d filenames.  \n\n\
  222.                Header Files contain the Strings to Print at the top of      \n\
  223.          every page of the listing, entire file can be up to %d bytes.";
  224.  
  225. /* -------------------------------------------------------------------- */
  226. /*
  227.       It all Starts With MAIN
  228. */
  229. main(argc, argv)
  230. int argc;
  231. char    **argv;
  232. {
  233. unsigned long int total_disk_free = 0;
  234. unsigned char ch;
  235. register int    i;
  236. int nextf = 0;                      /* index into fname[]                */
  237. long    thetime;
  238.  
  239.     ctrlbrk(c_break);                /* set control-break handler         */
  240.     double_strike = 1;                /* default to no double strike       */
  241.     header_flag   = 1;                /* default to codes and headers      */
  242.     header_lines  = 0;                /* no extra lines from header file   */
  243.     extra_lines   = 0;                /* no extra lines after functions    */
  244.  
  245.     ProgName = argv[0];                /* grab pointer to the programs name */
  246.  
  247.     time(&thetime);                    /* grab the DOS time and date        */
  248.     strcpy(Todayv,ctime(&thetime));    /* convert to ascii (LF at END OF STRING) */
  249.     strtok(Todayv,"\n");            /* strip the annoying LF off         */
  250.  
  251.     if (argc == 1)                    /*if only the program name given     */
  252.         Usage();                    /* if no args, show instructions     */
  253.  
  254.     for (i = 1; i < argc; i++) {    /* other parse command line          */
  255.         if (argv[i][0] == '-')  {    /* check for switch flag "-"         */
  256.             switch (toupper(argv[i][1])) { /* and go thru the switches   */
  257.  
  258.             case '@':                    /* Response file */
  259.                 nextf = ReadResponseFile(argv[i]);
  260.             break;
  261.  
  262.             case 'A':                    /* "*.???" Print all specified files */
  263.                 nextf = StarDot(argv[i]);
  264.             break;
  265.  
  266.             case 'C':                    /* Print codes/Dates/Time and page # */
  267.                 header_flag = 0;
  268.             break;
  269.  
  270.             case 'D':                    /* Double Strike function names      */
  271.                 double_strike = 3;
  272.             break;
  273.  
  274.             case 'H':                    /* Header file                       */
  275.                 ReadHeaderFile(argv[i]);
  276.             break;
  277.  
  278.             case 'L':                    /* Number of lines per page          */
  279.                 if ( ! argv[i][2]) {    /* if -L ?? (ie.. a space)           */
  280.                     if (++i >= argc)    /* see if another argument           */
  281.                         Usage();        /* if no then print Help             */
  282.  
  283.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  284.                         Usage();                    /* No! Print Help        */
  285.  
  286.                     PageLength = atoi (argv[i]);    /* assign number         */
  287.                 }
  288.                 else {        /* Switch came as -L?? form (with no space)      */
  289.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  290.                         Usage();                    /* No! Print Help        */
  291.  
  292.                     PageLength = atoi(&argv[i][2]);    /* assign number         */
  293.                 }
  294.             break;
  295.  
  296.             case 'N':                    /* Number Source Lines               */
  297.                 NumLines = 1;
  298.             break;
  299.  
  300.             case 'O':                    /* 1 function per page               */
  301.                 OnePerPage = 1;
  302.             break;
  303.  
  304.             case 'P':                    /* Starting Page Number              */
  305.                 if ( ! argv[i][2]) {    /* if -P ?? (ie.. a space)           */
  306.                     if (++i >= argc)    /* see if another argument           */
  307.                         Usage();        /* if no then print Help             */
  308.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  309.                         Usage();                    /* No! Print Help        */
  310.                     PageNumber = atoi (argv[i]);    /* assign number         */
  311.                 }
  312.                 else {        /* Switch came as -P?? form (with no space)      */
  313.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  314.                         Usage();                    /* No! Print Help        */
  315.                     PageNumber = atoi(&argv[i][2]);    /* assign number         */
  316.                 }
  317.             break;
  318.  
  319.             case 'Q':                    /* Print by Section                  */
  320.                 if ( ! argv[i][2]) {    /* if -Q ?? (ie.. a space)           */
  321.                     if (++i >= argc)    /* see if another argument           */
  322.                         Usage();        /* if no then print Help             */
  323.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  324.                         Usage();                    /* No! Print Help        */
  325.                     SectionNumber = atoi (argv[i]);    /* assign number         */
  326.                 }
  327.                 else {        /* Switch came as -Q?? form (with no space)      */
  328.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  329.                         Usage();                    /* No! Print Help        */
  330.                     SectionNumber=atoi(&argv[i][2]);/* assign number         */
  331.                 }
  332.                 sectionflg = 1;
  333.             break;
  334.  
  335.             case 'S':                    /* Sorted Table of Contents          */
  336.                 WantSorted = 0;
  337.             break;
  338.  
  339.             case 'T':                    /* Print Table of Contents Only      */
  340.                 table_contents = 1;        /* enable flag                       */
  341.                 if( argv[i][2] == '-')    /* if disabling TOC                  */
  342.                     table_contents = -1;/* disable it                        */
  343.             break;
  344.  
  345.             case 'W':                    /* Page Width                        */
  346.                 if ( ! argv[i][2]) {    /* if -W ?? (ie.. a space)           */
  347.                     if (++i >= argc)    /* see if another argument           */
  348.                         Usage();        /* if no then print Help             */
  349.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  350.                         Usage();                    /* No! Print Help        */
  351.                     PageWidth = atoi (argv[i]);        /* assign number         */
  352.                 }
  353.                 else {        /* Switch came as -W?? form (with no space)      */
  354.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  355.                         Usage();                    /* No! Print Help        */
  356.                     PageWidth = atoi(&argv[i][2]);    /* assign number         */
  357.                 }
  358.             break;
  359.  
  360.             case 'X':                    /* Extra Lines after Functions       */
  361.                 extra_lines = 1;
  362.             break;
  363.  
  364.             case '\0':                    /* End of string?(out of enviroment) */
  365.                 if (nextf >= N_FILES) {
  366.                     fprintf (stderr, "%s: too many files\n", argv[0]);
  367.                     exit (1);
  368.                 }
  369.                 fname[nextf++] = STDIN;        /* any in excess goes to STDIN   */
  370.             break;
  371.  
  372.             default:                        /* No arguments given            */
  373.                 Usage();                    /* show program instructions     */
  374.             break;
  375.             }
  376.         }
  377.         else {        /* Argument (argv[i]) wasn't a switch parmeter           */
  378.             if (nextf >= N_FILES) {
  379.                 fprintf (stderr, "%s: too many files\n", argv[0]);
  380.                 exit (1);
  381.             }
  382.             fname[nextf++] = argv[i];    /* copy pointer to filename          */
  383.         }
  384.     }
  385.  
  386.     if ( ! nextf)                /* No files were specified                   */
  387.         fname[nextf++] = STDIN; /* so use STDIN as the input file            */
  388.  
  389.     PageEnd = PageLength - (1 + PageLength / 20);
  390.  
  391.     StartTempFile();                    /* open temporary file               */
  392.  
  393.     for (i = 0; i < nextf; i++) {        /* walk thru file list               */
  394.         if (fname[i] == STDIN) {        /* if no files                       */
  395.             File = stdin;                /* assign stdin as input             */
  396.             Name = "Standard Input";    /* assign name for printout          */
  397.             fprintf(stderr,"Accepting Input from STDIN, ^Z to END\n");
  398.         }
  399.         else  {                            /* there was a filename              */
  400.             if( (File = fopen( Name = fname[i], "r" )) == NULL )  {
  401.                 fprintf (stderr, "%s: Can't open file \"%s\"\n",
  402.                         ProgName, Name );
  403.                 continue;                /* keep going if not found           */
  404.             }
  405.             else {                        /* file opened OK so read            */
  406.                 fprintf(stderr, "\nReading File #%3d of %3d: \" %s \"",
  407.                         i+1, nextf, fname[i]);
  408.  
  409.                 memfree = coreleft();        /* compute amount of free memory */
  410.                 memfree = ( (memfree > 32767L) ?/* if to much memory then    */
  411.                                    32767L  :    /* set max for setvbuf       */
  412.                                    memfree );    /* else take as much as u can*/
  413.  
  414.                 if( setvbuf(File, NULL, _IOFBF, (int) memfree) != 0) {
  415.                     fprintf(stderr,"Input Buffer failed to allocate.\n");
  416.                 }
  417.             }
  418.         }
  419.         List();                    /* Read File in and process data             */
  420.  
  421.         if (File != stdin) {    /* if it's not STDIN                         */
  422.             fclose(File);        /* close file & deallocate buffer            */
  423.         }
  424.     }
  425.  
  426.     if( PageNumber > 1 || LineNumber > 0 )
  427.         BreakPage();
  428.  
  429.     EndTempFile();                /* Close Temporary File                     */
  430.  
  431.     fprintf(stderr,"\n\n");
  432.  
  433.     getdfree(0, &disk_space);/* find out free disk space after cpr$.tmp created */
  434.  
  435.     total_disk_free =    ( ( (long)disk_space.df_bsec   *    /* bytes per sector    */
  436.                             (long)disk_space.df_sclus) *    /* sectors per cluster */
  437.                             (long)disk_space.df_avail);        /* clusters available  */
  438.  
  439.     findfirst(TEMPORARY_FILENAME,&fblock,0);    /* read temp file size in    */
  440.  
  441.     if(fblock.ff_fsize >= total_disk_free) {    /* see if copy can be output */
  442.         fprintf(stderr,"Insufficient Disk Space!\n\
  443.                         \nMinimum of %lu bytes needed.\
  444.                         \n%lu bytes are available\n\
  445.                         \nDo You wish to continue? (Y/N)",
  446.                         fblock.ff_fsize, total_disk_free);
  447.         do {
  448.             ch = (toupper(getche()) );
  449.         }
  450.         while((ch != 'Y') && (ch != 'N'));
  451.  
  452.         if(ch != 'Y')
  453.             Done();                    /* Delete Temporary File             */
  454.  
  455.         fprintf(stderr,"\n\n");
  456.     }
  457.  
  458.     if((!table_contents) ||            /* if TOC and file enabled           */
  459.         (table_contents == 1))        /* or TOC only     enabled           */
  460.         DumpTableOfContents();        /* Print Table of Contents           */
  461.  
  462.     if((!table_contents) ||            /* if TOC and file enabled           */
  463.         (table_contents == -1))        /* or no TOC                         */
  464.         DumpTempFile();                /* then dump the file                */
  465.  
  466.     Done();                            /* Clean things up and leave         */
  467. }
  468. /*****************************************************************************/
  469. Usage()
  470. {
  471.         fprintf (stderr,"Usage: %s SWITCHES filename [...]",ProgName);
  472.         fprintf (stderr,option_list ,
  473.                    MAJOR_VERSION, MINOR_VERSION, LENGTH, WIDTH,
  474.                    MAX_FNAME_SIZE-1, N_FILES, MAX_HDR_BYTES);
  475.         exit(1);
  476. }
  477. /*****************************************************************************/
  478. StartTempFile()
  479. {
  480.     TempName = TEMPORARY_FILENAME;            /* Temporary Filename */
  481.  
  482.     if( (TempFile = fopen(TempName, "w")) == NULL ) {
  483.         fprintf (stderr, "%s: Can't open temp file!\n", ProgName);
  484.         exit(1);
  485.     }
  486. }
  487. /*****************************************************************************/
  488. EndTempFile()
  489. {
  490.     fclose (TempFile);
  491. }
  492. /*****************************************************************************/
  493. DumpTempFile()
  494. {
  495. int     fd,n;
  496. char    buff[1025];
  497.  
  498.     if ((fd = open (TempName, O_RDONLY | O_RAW)) == -1) {
  499.         fprintf (stderr, "%s: can't open temp file\n", ProgName);
  500.         exit (1);
  501.     }
  502.  
  503.     while ((n = read (fd, buff, 1024)) != 0) {
  504.         if (write (1, buff, n) == -1) {
  505.             fprintf (stderr, "%s: write error (1)\n", ProgName);
  506.             exit (1);
  507.         }
  508.     }
  509. }
  510. /*****************************************************************************/
  511. Done()
  512. {
  513.     if( TempName )            /* if you created a file  */
  514.         unlink( TempName );    /* Delete temporary file  */
  515.     exit(0);                /* and leave the hard way */
  516. }
  517. /*****************************************************************************/
  518. List()            /* Process Incoming File */
  519. {
  520. register int    bp;
  521. char            buffer[257];
  522.  
  523.     if( sectionflg ) {                            /* if by section             */
  524.         PageNumber = 1;                            /* Pages start at 1          */
  525.         LineNumber = 0;                            /* Lines reset each time     */
  526.     }
  527.  
  528.     NewPage();                                    /* bump page & output header */
  529.     NewFile();
  530.  
  531.     bp = Braces = 0;                            /* no begin page and braces  */
  532.  
  533.     while( fgets(buffer, 256, File) != NULL ) {    /* read a line upto 256 bytes*/
  534.         Rs(buffer);                                /* Remove Trailing Spaces    */
  535.  
  536.         if( bp )                                /* if beginning page         */
  537.             NewFunction();                        /* setup for new function    */
  538.  
  539.         if( (LineNumber + 1) > PageEnd )         /* if going past page end   */
  540.             NewPage();                             /* start a new page         */
  541.  
  542.         if(!Braces && LooksLikeFunction(buffer)) /* no braces and a function */
  543.             AddToTableOfContents();                 /* then add to TOC          */
  544.  
  545.         bp = PutLine(buffer);
  546.         LineNumber++;
  547.     }
  548.     if( sectionflg )                             /* if by sections           */
  549.         SectionNumber ++;                         /* Bump to next Section     */
  550. }
  551. /*****************************************************************************/
  552. NewPage()                        /* Process New Page                          */
  553. {
  554.     if( LineNumber > HEADER_SIZE )  {
  555.         if( PageNumber >= 0 ) {
  556.             PageNumber ++;        /* bump Page Number      */
  557.         }
  558.         BreakPage();            /* form feed if allowed  */
  559.         LineNumber = 0;            /* set flag for a header */
  560.     }
  561.     if( LineNumber == 0 )        /* Each new page         */
  562.         PutHeader();            /* Outputs a Header      */
  563. }
  564. /*****************************************************************************/
  565. NewFile()
  566. {
  567. register int    i, l;
  568. char            temp[80];
  569.  
  570.     if (TocCount >= TOC_LEN) {
  571.         fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
  572.         exit (1);
  573.     }
  574.  
  575.     if( (Toc[TocCount] = (char *) malloc(130)) == NULL)    /* allocate some memory */
  576.         ReportMemoryError();
  577.  
  578.     sprintf (Toc[TocCount], "\n\tFile: %s ", Name);    /* to put filename into */
  579.     l = strlen(Toc[TocCount]) - 1;                    /* and findout how long it is */
  580.  
  581.     if( l < 64 )  {                                    /* if not to long */
  582.         i = (64 - l) / 8;                            /* calc. TAB increment */
  583.         for( l=0; l < i; ++l )                        /* keep within 64 columns */
  584.             strcat(Toc[TocCount],"\t");                /* and put some TAB's out */
  585.     }
  586.  
  587.     file_stats(Name);                                /* findout file stats  */
  588.  
  589.     if(! sectionflg ) {
  590.         sprintf (temp, "  Page %4d  (%s  %s)\n",    /* Page #, Time & date */
  591.             PageNumber, file_date_buff, file_time_buff);
  592.     }
  593.     else {
  594.         sprintf (temp, "  Section %4d (%s  %s)\n",    /* Section, Time & Date*/
  595.             SectionNumber, file_date_buff, file_time_buff);
  596.     }
  597.  
  598.     strcat(Toc[TocCount], temp);                    /* copy to main buffer */
  599.     ++ TocCount;                                    /* bump the entries    */
  600.  
  601.     if (NumLines)                                    /* if numbering lines  */
  602.         Number  = 1;                                /* reset linenumber    */
  603.  
  604.     InComment = InString = 0;                    /* not in comment or string */
  605. }
  606. /****************************************************************************/
  607. PutLine(l)
  608. register char   *l;
  609. {
  610. register char   c;
  611. int             bp;
  612. char            *save;
  613. char            *section, *p;
  614. int             offset;
  615. char            Digits[15];
  616. int             Size;
  617. int             pos;
  618.  
  619.     bp = 0;
  620.     for( save = expand(l);
  621.         ( (c = *l) != 0);
  622.                 ++l )    {                /* bump thru the string */
  623.  
  624.         if( InComment )                    /* if your in a comment  */
  625.             l = EndComment(l);            /* process till your out */
  626.         else
  627.         if( InString )                    /* if your in a string   */
  628.             l = EndString(l);            /* process till your out */
  629.         else
  630.         switch(c)  {                    /* it must be something  */
  631.             case '{':                    /* curly brace IN        */
  632.                 ++Braces;                /* increment brace count */
  633.             break;
  634.  
  635.             case '}':                    /* curly brace OUT       */
  636.                 if( --Braces == 0)        /* coming out yet?       */
  637.                     if (*(l+1) == ';')    /* is it structure?      */
  638.                         ++l;            /* continue thru string  */
  639.                     else
  640.                     if(extra_lines)         /* if option enabled    */
  641.                         bp = 1;             /* flag for extra lines */
  642.             break;
  643.  
  644.             case '\'':                    /* Forward Slash         */
  645.                 ++l;                    /* continue thru string  */
  646.             break;
  647.  
  648.             case '"':                    /* Quotation Mark        */
  649.                 InString = 1;            /* must be in a string   */
  650.             break;
  651.  
  652.             case '/':                    /* Start of Comment      */
  653.                 if( *(l+1) == '*' ) {    /* is next character * ? */
  654.                     InComment = 1;        /* must be in a comment  */
  655.                     ++l;                /* continue thru string  */
  656.                 }
  657.             break;
  658.         }
  659.     }
  660.  
  661.     if (NumLines)  {                    /* if line numbering enabled */
  662.         sprintf (Digits,"[%d]  ", Number);    /* make a string         */
  663.         Size = strlen(Digits);                /* calc. its size        */
  664.     }
  665.     else {
  666.         Size = 0;                        /* else it's size is 0       */
  667.     }
  668.  
  669.     if (strlen(save) +                    /* if original strings size  */
  670.                Size  >                    /* and the size of numbers   */
  671.                PageWidth)  {            /* are bigger than the width */
  672.         section = substr1(save, 0, PageWidth - Size);
  673.  
  674.         if (section[strlen(section) - 1] != ' ')
  675.             if (NULL == (p = strrchr(section, ' ')))
  676.                 offset = strlen(section);
  677.             else
  678.                 offset = p - section;
  679.             else
  680.                 offset = strlen(section) - 1;
  681.  
  682.         section[offset] = NULL;
  683.  
  684.         if (NumLines)  {    /* if line numbering is enabled */
  685.             fprintf (TempFile, "[%d]  %s\n", Number++, section);
  686.         }
  687.         else  {
  688.             fprintf (TempFile, "%s\n", section);
  689.         }
  690.  
  691.         pos = offset + 1;
  692.         do  {
  693.             section = substr1(save, pos, pos + PageWidth - 8);
  694.             if (strlen(save) - pos + 8 > PageWidth)
  695.                 if (section[strlen(section) - 1] != ' ')
  696.                     if (NULL == (p = strrchr(section, ' ')))
  697.                         offset = strlen(section);
  698.                     else
  699.                         offset = p - section;
  700.                     else
  701.                         offset = strlen (section) - 1;
  702.                     else
  703.                         offset = strlen(section);
  704.  
  705.                 section[offset] = NULL;
  706.  
  707. /** ----------------------------------------------------------------- **/
  708. /* Removed this for some reason
  709. /*
  710. /*                if (section[strlen(section) - 1] == '\n')
  711. /*                    section[strlen(section) - 1] = NULL;
  712. */
  713.  
  714. /*  Line is to long for pagewidth so continue on next line */
  715.  
  716.                 fprintf (TempFile, "C       %s\n", section);
  717.                     if (++LineNumber > PageEnd)
  718.                         NewPage();
  719.             }
  720.             while ((pos += offset + 1) < strlen(save));
  721.         }
  722.         else  {
  723.             if (NumLines)        /* if line numbering enabled */
  724.                 fprintf (TempFile, "[%d]  %s\n", Number++, save);
  725.             else
  726.                 fprintf (TempFile, "%s\n", save);
  727.         }
  728.     return(bp);
  729. }
  730. /*****************************************************************************/
  731. NewFunction()                    /* Process New Function                     */
  732. {
  733. register int    i;
  734.  
  735.     if( LineNumber > (PageLength * 3 / 4) )       /*  49.5 lines            */
  736.         NewPage();
  737.     else  {
  738.         if (!OnePerPage)  {                    /* if mult. functions per page  */
  739.             for( i=0; i < (PageLength/7); ++i )
  740.                 putc ('\n', TempFile);        /* add extra lines              */
  741.                 LineNumber += PageLength/7; /* set line counter also        */
  742.             }
  743.             else
  744.                 NewPage();                    /* otherwise its 1 func. per page*/
  745.     }
  746. }
  747. /*****************************************************************************/
  748. BreakPage()                        /* Process Page Break                        */
  749. {
  750.     if(header_flag)                /* if its allowed send a FORM FEED           */
  751.         putc (BP, TempFile);
  752. }
  753. /*****************************************************************************/
  754. PutHeader()
  755. {
  756. register int    i, l, j;
  757.  
  758.     if(header_flag)             /* if its allowed send a COMPRESSED Code */
  759.         putc (COMPRESSED, TempFile);
  760.  
  761.     putc ('\n', TempFile);
  762.  
  763.     if(header_flag ) {            /* if its allowed send out the HEADER */
  764.  
  765.         l = strlen(Name);        /* Filename or Table of Contents label length */
  766.  
  767.         for( j=0; j < double_strike; ++j) {
  768.             fprintf (TempFile, "%s", Name);    /* Write out Filename or TOC */
  769.             if( (j < 2) && (double_strike == 3) )
  770.                 putc('\r', TempFile);        /* Provide for Double Strike CR */
  771.         }
  772.         if( PageNumber > 0 ) {                /* if your not on the TOC pages */
  773.             for( i = (l+7)/8; i < 6; ++i )
  774.                 putc ('\t', TempFile);        /* Tab out for position         */
  775.  
  776.             if(! sectionflg ) {
  777.                 fprintf (TempFile, "%s\tPage: %d\n\n\n", Todayv,PageNumber);
  778.             }
  779.             else {
  780.                 fprintf (TempFile, "%s\tSection %3d - %d\n\n\n",
  781.                     Todayv,SectionNumber,PageNumber);
  782.             }
  783.  
  784.             if(header_lines)                        /* Header for TOP OF PAGE */
  785.                 fprintf (TempFile, "%s", header_buffer);
  786.         }
  787.         else {    /* 1st line of Table of Contents page gets the time and date */
  788.  
  789.             for( i = (l+7)/8; i < 6; ++i )            /* Tab out for time/date  */
  790.                 putc ('\t', TempFile);
  791.  
  792.             fprintf (TempFile, "%s\n\n", Todayv);        /* Todays Time and Date   */
  793.  
  794.             if(header_lines)                        /* Header for TOP OF PAGE */
  795.                 fprintf (TempFile, "%s", header_buffer);
  796.         }
  797.     }
  798.     LineNumber += (HEADER_SIZE + header_lines);        /* bump line number counter */
  799. }
  800. /*****************************************************************************/
  801. LooksLikeFunction(s)
  802. register char   *s;
  803. {
  804. register char   *p;
  805. char            *save;
  806. int             Cnt, nosl,nolp,norp,flg;
  807. char            Digits[15];
  808. int             AddOne = 0;
  809.  
  810.     if( InComment || InString)        /* if your in a comment or in a string */
  811.         return(0);                    /* just leave and return 0             */
  812.  
  813.     p = FunctionName;                /* assign pointer to function name string */
  814.     save = s;                        /* save address of string                 */
  815.  
  816.     nosl = nolp = norp = 0;            /* no left or right paren or no slash     */
  817.  
  818.     flg = 1;
  819.  
  820.     for(; *s && flg  ; s++)  {        /* go until end of string or flag is set  */
  821.         switch  (*s)  {                /* switch on each character in string     */
  822.             case  '(':                /* is it a left paren?                    */
  823.                 if (!nolp) {        /* if no left paren already               */
  824.                     nolp = 1;        /* flag that you've got one               */
  825.  
  826. /* 3/4/87 added following line to include ARGS in TOC */
  827.  
  828.                     *p++ = *s;        /* move byte of ARG into function buffer */
  829.                 }
  830.                 else
  831.                     return(0);        /* or return if you've already had one    */
  832.             break;
  833.  
  834.             case  ')':                /* is it a right paren?                   */
  835.                 if (nolp && !norp) {/* if already a left paren and no right yet */
  836.                     norp = 1;        /* flag that you've got a right paren     */
  837.  
  838. /* 3/4/87 added following line to include ARGS in TOC */
  839.                     *p++ = *s;        /* move byte of ARG into function buffer  */
  840.                 }
  841.                 else
  842.                     return(0);        /* or return if conditions were'nt right  */
  843.             break;
  844.  
  845.             default:                /* everything comes thru here             */
  846.                 if (!nolp)  {        /* if no left paren yet                   */
  847.                     if (isiechr(*s))  {    /* is it alpha,digit,'_*\t\n'?        */
  848.                         if (isidchr(*s))/* is it alpha,digit,'_' or ' '?      */
  849.                             *p++ = *s;    /* if it is store the byte for TOC    */
  850.                         else
  851.                             p = FunctionName;    /* start over if '*\t\n' & nolp */
  852.                     break;
  853.                     }
  854.                     else
  855.                         return(0);    /* return if conditions weren't right     */
  856.                 }
  857.  
  858.                 if (!norp)  {        /* if no right paren yet                  */
  859.                     if (isiechr(*s) || *s == ',') { /* is it alpha,digit,'_ *\t\n'?*/
  860.  
  861. /* 3/4/87 added following line to include ARGS in TOC */
  862.                         *p++ = *s;    /* move byte of ARG in function buffer    */
  863.                         break;
  864.                     }
  865.                     else
  866.                         return(0);        /* return if conditions weren't right */
  867.                 }
  868.  
  869.                 if (Cmemb(*s," \t\n\r") && !nosl)    /* is it ' \t\n\r' or no slash yet */
  870.                     break;
  871.  
  872.                 if (*s == '/' && !nosl)  {    /* is it a '/' and no slash yet   */
  873.                     nosl = 1;                /* flag that you've got one       */
  874.                     break;
  875.                 }
  876.  
  877.                 if (*s == '*' && nosl)  {    /* if its '*' & you got a slash already */
  878.                     flg = 0;                /* set flag to abort loop         */
  879.                     break;
  880.                 }
  881.                 return(0);                    /* return if conditions not right */
  882.         } /* end of switch */
  883.     }        /* end of for loop */
  884.  
  885.     if (nolp != 1)                            /* return if no left paren found  */
  886.         return(0);
  887.  
  888.     *p = '\0';                                /* else terminate function buffer */
  889.  
  890.     if (NumLines)  {                        /* if line numbering enabled      */
  891.         sprintf (Digits,"[%d]  ", Number);    /* format number into string      */
  892.         Cnt = strlen(Digits) + AddOne;
  893.         while (Cnt-- > 0)
  894.             putc (' ', TempFile);
  895.         AddOne = 0;
  896.     }
  897. /*
  898.  * This will cause the function name part of the line to
  899.  * be double striken.
  900. */
  901.     if( double_strike == 3) {
  902.         while (*save && *save != '(')        /* double strike up to func  name */
  903.             putc (*save++, TempFile);
  904.         putc ('\r', TempFile);                /* use CR for doublestrike        */
  905.     }
  906.     return(1);
  907. }
  908. /****************************************************************************/
  909. AddToTableOfContents()
  910. {
  911. register int    l;
  912. register char   *p;
  913.  
  914.     if (TocCount >= TOC_LEN) {
  915.         fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
  916.         exit (1);
  917.     }
  918.     l = strlen(FunctionName);                    /* find how long name is */
  919.     p = Toc[TocCount] = (char *) malloc(l+1);    /* allocate just enough memory */
  920.  
  921.     if( p == NULL)                                /* did it really allocate     */
  922.         ReportMemoryError();                    /* No! then report error      */
  923.  
  924.     strcpy(p, FunctionName);                    /* copy the name to new space */
  925.     TocPages[TocCount] = PageNumber;            /* plug the page number in    */
  926.     ++TocCount;                                    /* bump the count             */
  927. }
  928. /****************************************************************************/
  929. DumpTableOfContents()
  930. {
  931. register int    i, j, l;
  932.  
  933.     if( TocCount == 0 )        /* if there nothing to print */
  934.         return;                /* then just return          */
  935.  
  936.     if (WantSorted)            /* if you wanted it sorted by page number */
  937.         SortTableOfContents();    /* then we must sort it first         */
  938.  
  939.     Name = "Table of Contents";    /* give me a title for the page       */
  940.  
  941.     PageNumber = -1;            /* Table of Contents pages are not numbered */
  942.     LineNumber = 0;                /* and neither are the lines          */
  943.     TempFile = stdout;            /* default output to standard out     */
  944.  
  945.     NewPage();                    /* start out creating a new page      */
  946.  
  947.     for( i=0; i < TocCount; ++i ) {
  948.         if( Toc[i][0] == '\n' ) {
  949.             if( (LineNumber + 5) > PageEnd )
  950.                 NewPage();
  951.             printf("%s", Toc[i]);
  952.             LineNumber += 2;
  953.             continue;
  954.         }
  955.  
  956.         if( ++LineNumber > PageEnd )/* if going off end of page           */
  957.             NewPage();                /* start a new page                   */
  958.  
  959.         printf("\t\t%s ", Toc[i]);    /* print func. name in TOC            */
  960.         l = strlen(Toc[i]);            /* length if function name with parms */
  961.  
  962.         for( j=l; j < 48; ++j )        /* put dots out to column 48          */
  963.             putchar('.');            /* put dots out to page num. in TOC   */
  964.  
  965.             printf(" %d\n", TocPages[i]);    /* print page number for function */
  966.     }
  967.  
  968.     if(header_flag)        /* if control codes are allowed        */
  969.         putchar(BP);    /* print a Form Feed                   */
  970.     else
  971.         putchar('\n');    /* otherwise its a New Line            */
  972.  
  973.     fflush(stdout);        /* make sure everything is written out */
  974. }
  975. /****************************************************************************/
  976. /*
  977.        Sort Table of Contents by Page number rather than function name
  978. */
  979. SortTableOfContents()
  980. {
  981. register int    i, tempint;
  982. char            *tempchar;
  983. int                flag;
  984.  
  985.     do {
  986.         flag = 0;                /* default to already sorted */
  987.  
  988.         for (i = 0; i < TocCount - 1; i++) {    /* look at them all */
  989.             if (Toc[i][0] == '\n' || Toc[i+1][0] == '\n')
  990.                 continue;       /* don't sort across file names */
  991.  
  992.             if (strcmp (Toc[i], Toc[i+1]) > 0) {/* compare the strings        */
  993.                 tempchar = Toc[i];                /* copy to temp pointer       */
  994.                 Toc[i] = Toc[i+1];                /* swap the pointers in array */
  995.                 Toc[i+1] = tempchar;            /* put the temp pointer back  */
  996.                 tempint = TocPages[i];            /* grab the page number       */
  997.                 TocPages[i] = TocPages[i+1];    /* swap page numbers          */
  998.                 TocPages[i+1] = tempint;        /* put the temp page number back */
  999.                 flag = 1;                        /* indicate you've swapped    */
  1000.             }
  1001.         }
  1002.     }
  1003.     while (flag);            /* go until no more swaps can be made */
  1004. }
  1005. /****************************************************************************/
  1006. char *EndComment(p)            /* Process string until you come out of COMMENT */
  1007. register char   *p;
  1008. {
  1009. register char   c;
  1010.  
  1011.     while( (c = *p++) != 0 )            /* while there are chars to look at */
  1012.         if( c == '*' && *p == '/' ) {    /* and there a splat or a slash     */
  1013.             InComment = 0;                /* say your not in the comment      */
  1014.             break;                        /* and leave the loop               */
  1015.         }
  1016.     return(p-1);                        /* returning the new pointer addr.  */
  1017. }
  1018. /*****************************************************************************/
  1019. char *EndString(p)            /* Process string until you come out of STRING  */
  1020. register char   *p;
  1021. {
  1022. register char   c;
  1023.  
  1024.     while( (c = *p++) != 0 )            /* while there are chars to look at */
  1025.         if( c == '\\' ) {                /* and forward slashs for next line */
  1026.             continue;                    /* means "Just read on McDuck"      */
  1027.         }
  1028.         else if( c == '"' ) {            /* if you found the ending quote    */
  1029.             InString = 0;                /* say your not in a string anymore */
  1030.             break;                        /* and leave the loop               */
  1031.         }
  1032.     return(p-1);                        /* returning the new pointer addr.  */
  1033. }
  1034. /****************************************************************************/
  1035. /*
  1036.  *      This is the function substr1().  The calling sequence is:
  1037.  *
  1038.  *                      substr1(string, startpos, endpos).
  1039.  *
  1040.  *      The function returns a pointer to a static string (written over -
  1041.  *      on subsequent calls) which is a substring of the string `string'
  1042.  *      starting at `startpos' (the first position is 0 (zero)) and ending
  1043.  *      at `endpos' (non-inclusive).  All arguments must be present or
  1044.  *      strange things happen with the system stack.
  1045.  *
  1046.  *      An example of the use is:
  1047.  *
  1048.  *              x = substr1(string, 2, 5);
  1049.  *              (where string == "This is a test.")
  1050.  *
  1051.  *      This call returns a pointer to:
  1052.  *              "is "
  1053.  *      An error code of -1 is returned is the `endpos' is greater than
  1054.  *      `startpos'
  1055.  *
  1056.  *                                              Lance E. Shepard
  1057.  */
  1058. char *substr1(string, start, end)
  1059. char    *string;
  1060. int     start;
  1061. int     end;
  1062. {
  1063. static char  retstr[MAX_S];
  1064. int loop1;
  1065. int loop2;
  1066.  
  1067.     if (end < start)  {
  1068.         exit(-1);
  1069.     }
  1070.  
  1071.     for (loop2 = 0; loop2 < MAX_S; loop2++)
  1072.         retstr[loop2] = NULL;
  1073.  
  1074.     for (loop1 = start, loop2 = 0; string[loop1] != NULL &&
  1075.          loop1 < end && loop2 <= MAX_S; loop1++, loop2++)
  1076.             retstr[loop2] = string[loop1];
  1077.  
  1078.     retstr[++loop2] = NULL;
  1079.     return(retstr);
  1080. }
  1081. /****************************************************************************/
  1082. /*
  1083.  *      This is the function `char *expand().'  This function takes as
  1084.  *      an argument a NULL terminated string and replaces all occurances
  1085.  *      of the tab character with 8 (eight) spaces.  The function returns
  1086.  *      a pointer to a static string which is overwritten on subsequent
  1087.  *      calls.
  1088. */
  1089. /****************************************************************************/
  1090. char *expand(string)
  1091. char *string;
  1092. {
  1093. int count;
  1094. static char retstr[MAX_S];
  1095.  
  1096.     for (count = 0; count < MAX_S; retstr[count++] = NULL)
  1097.         ;
  1098.  
  1099.     for (count = 0; *string != NULL; count++, string++)  {
  1100.         if (*string == '\t')  {
  1101.             retstr[count] = ' ';
  1102. /*             while (((count + 1) % 8) != 0)     */
  1103.                 while (TabDef[count] != 'T')
  1104.                     retstr[++count] = ' ';
  1105.         }
  1106.         else
  1107.             retstr[count] = *string;
  1108.     }
  1109.     retstr[count] = NULL;
  1110.     return(retstr);
  1111. }
  1112. /****************************************************************************/
  1113. char *Rs(s)             /* strip trailing blanks from string  */
  1114. char s[];
  1115. {
  1116. int n;
  1117.     for (n=strlen(s)-1 ; n >= 0 && isspace(s[n]) ; n--)
  1118.         ;                /* find the last space in the string */
  1119.     s[n+1] = '\0';        /* plop a null char on top of it     */
  1120.     return(s);            /* return pointer to string          */
  1121. }
  1122. /****************************************************************************/
  1123. int Cmemb(a,b)  /*  is character "a" a member of string "b"  */
  1124. char  a, *b;
  1125. {
  1126.     while  (*b)                /* go until the null character */
  1127.         if (a == *b++)        /* looking for the character and bumping the pointer */
  1128.             return(1);        /* returning 1 if its found */
  1129.     return( (!a) ? 1 : 0 );    /* return 0 if "a" was a non-zero character */
  1130. }
  1131. /****************************************************************************/
  1132. StarDot(file_string)
  1133. char * file_string;
  1134. {
  1135. extern char filenames[N_FILES][MAX_FNAME_SIZE];
  1136. extern char fnames[N_FILES];
  1137. extern struct ffblk fblock;
  1138. extern struct dfree disk_space;
  1139.  
  1140. unsigned long int total_file_size = 0;
  1141. unsigned long int total_disk_free = 0;
  1142. int done;
  1143. int i = 0;
  1144.     file_string += 2;                        /* bump past -A switch */
  1145.  
  1146.     if( (done = findfirst(file_string,&fblock,0)) != 0) {/* Attempt 1st file read */
  1147.         fprintf(stderr,"No Files Found\n");
  1148.         exit(1);
  1149.     }
  1150.     while(!done && i < N_FILES) {        /* go until done or to many files */
  1151.         strcpy(&filenames[i][0],fblock.ff_name);/* copy names into array  */
  1152.         fname[i] = &filenames[i++][0];        /* copy pointer to name       */
  1153.  
  1154.         total_file_size += fblock.ff_fsize;    /* keep running total of filesizes */
  1155.  
  1156.         done = findnext(&fblock);            /* read next availables file info  */
  1157.     }
  1158.     if( i == N_FILES)
  1159.         fprintf(stderr,"Printing ONLY 1st %d Files\n", N_FILES);
  1160.  
  1161.     getdfree(0, &disk_space);                /* find free disk space */
  1162.     total_disk_free =    (     ((long)disk_space.df_bsec  *    /* convert to bytes */
  1163.                             (long)disk_space.df_sclus) *
  1164.                             (long)disk_space.df_avail);
  1165.  
  1166.     if((total_file_size * 2) >= total_disk_free) {
  1167.         fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
  1168.                         \nYou Have %lu bytes free\n",
  1169.                         total_file_size * 2, total_disk_free);
  1170.         exit(1);
  1171.     }
  1172.     return(i);            /* return new number of files */
  1173. }
  1174. /*****************************************************************************/
  1175. ReportMemoryError()
  1176. {
  1177.     fprintf(stderr,"Memory Allocation Error\n");
  1178.  
  1179.     if( TempName ) {            /* if there is a file to work on */
  1180.         EndTempFile();            /* Make sure file is closed */
  1181.         unlink( TempName );        /* Delete temporary file */
  1182.     }
  1183.  
  1184.     exit(1);
  1185. }
  1186. /*****************************************************************************/
  1187. ReadHeaderFile(header_file)
  1188. char *header_file;
  1189. {
  1190. extern char        header_buffer[MAX_HDR_BYTES];
  1191. extern int        header_lines;
  1192. int ch;
  1193. int i = 0;
  1194. int x = 0;
  1195. char *string;
  1196.  
  1197.     header_file += 2;        /* strip the "-h" from the string */
  1198.     if(( Hfile = fopen(header_file, "r")) == NULL) {
  1199.         fprintf(stderr,"Can't Open Header File %s\n",header_file);
  1200.         exit(1);            /* terminate abruptly */
  1201.     }
  1202.     else {
  1203. /* read entire file that is up to MAX_HDR_BYTES characters long */
  1204.         while( (ch = fgetc(Hfile)) != EOF) {
  1205.             header_buffer[i++] = (unsigned char) ch;
  1206.             if(i < MAX_HDR_BYTES)
  1207.                 continue;
  1208.             else
  1209.                 break;
  1210.         }
  1211.         header_buffer[i] = '\0';    /* terminate buffer */
  1212.  
  1213.         fclose(Hfile);        /* and close the file */
  1214.  
  1215.         for(x = 0, string = header_buffer; x <= i; x++) {
  1216.             if(*string++ == '\n')        /* count number of line feeds */
  1217.                 header_lines++;            /* tell the NewPage Function  */
  1218.         }
  1219.     }
  1220. }
  1221. /*****************************************************************************/
  1222. ReadResponseFile(response_file)
  1223. char *response_file;
  1224. {
  1225. char fpntr[80];                /* area for string to be read into */
  1226. extern char filenames[N_FILES][MAX_FNAME_SIZE];
  1227. extern char fnames[N_FILES];
  1228. extern struct ffblk fblock;
  1229. extern struct dfree disk_space;
  1230.  
  1231. unsigned long int total_file_size = 0;
  1232. unsigned long int total_disk_free = 0;
  1233.  
  1234. int i = 0;
  1235.  
  1236.     response_file += 2;    /* strip the "-@" from the string */
  1237.     if(( Rfile = fopen(response_file, "r")) == NULL) {
  1238.         fprintf(stderr,"Can't Open Response File %s\n",response_file);
  1239.         exit(1);            /* terminate abruptly */
  1240.     }
  1241.     else {
  1242. /* read a entire line from the Rfile that is up to 80 characters long */
  1243.         while(fgets(fpntr,80,Rfile) != NULL && i < N_FILES) {
  1244.             strtok(fpntr," \n");                /* strip to LF or space */
  1245.             strcpy(&filenames[i][0],fpntr);        /* copy names into array */
  1246.             fname[i] = &filenames[i++][0];        /* copy pointer to name */
  1247.  
  1248.             findfirst(fpntr,&fblock,0);            /* read file size in */
  1249.  
  1250.             total_file_size += fblock.ff_fsize;    /* keep running total of filesizes */
  1251.         }
  1252.         fclose(Rfile);        /* and close the file */
  1253.  
  1254.         getdfree(0, &disk_space);        /* find free disk space */
  1255.         total_disk_free =    ( ((long)disk_space.df_bsec * (long)disk_space.df_sclus) *
  1256.                                (long)disk_space.df_avail);
  1257.  
  1258.         if((total_file_size * 2) >= total_disk_free) {
  1259.             fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
  1260.                             \nYou Have %lu bytes free\n",
  1261.                             total_file_size * 2, total_disk_free);
  1262.             exit(1);
  1263.         }
  1264.         return(i);            /* return new number of files */
  1265.     }
  1266.     return(0);
  1267. }
  1268. /*****************************************************************************
  1269.     This routine is executed when the CONTROL-BREAK key combination is hit
  1270. *****************************************************************************/
  1271. c_break()
  1272. {
  1273.     fprintf(stderr,"Control-Break hit.  Program aborting ...\n");
  1274.  
  1275.     if( TempName ) {            /* if you created a file    */
  1276.         EndTempFile();            /* Make sure file is closed */
  1277.         unlink( TempName );        /* Delete temporary file    */
  1278.     }
  1279.     return(0);                    /* ABORT sequence           */
  1280. }
  1281. /*****************************************************************************/
  1282. file_stats(filename)
  1283. char *filename;
  1284. {
  1285. extern struct ffblk fblock;
  1286.  
  1287.     findfirst(filename,&fblock,0);        /* read data into structure     */
  1288.  
  1289. /* ------------------- Show date in standard format --------------------*/
  1290.  
  1291.     sprintf(file_date_buff,"%02d-%02d-%02d",
  1292.         ((fblock.ff_fdate >> 5) & 0x0f),   /* month     */
  1293.         (fblock.ff_fdate & 0x1f)       ,   /* day       */
  1294.         ((fblock.ff_fdate >> 9) + 80  ));  /* year      */
  1295.  
  1296. /* -----------------   Show time in 12 Hour Format   ------------------- */
  1297.     if ( (fblock.ff_ftime >> 0x0b) <= 12)
  1298.     {
  1299.         sprintf(file_time_buff,"%02d:%02d",
  1300.         (fblock.ff_ftime >> 0x0b),
  1301.         ((fblock.ff_ftime >> 5 ) & 0x3f ));  /* minutes   */
  1302.     }
  1303.     else
  1304.     {
  1305.         sprintf(file_time_buff,"%02d:%02d",
  1306.         ((fblock.ff_ftime >> 0x0b) - 12),
  1307.         ((fblock.ff_ftime >> 5 ) & 0x3f ));  /* minutes   */
  1308.     }
  1309. /* ------------------     Decipher whether its AM or PM  ---------------- */
  1310.     if ( (fblock.ff_ftime >> 0x0b) < 12)
  1311.         strcat(file_time_buff," am");    /* for AM */
  1312.     else
  1313.         strcat(file_time_buff," pm");    /* for PM */
  1314. }
  1315. /*************************************************************************/